package cn.pku.edu.cs.ldn.util;

import android.app.ActivityManager;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.support.v4.util.LruCache;
import android.util.Log;

public class BitmapCacheUtil {
	private static final String TAG = "BitmapCacheUtil";
	private static final boolean DEBUG = true;

	private static LruCache<String, Bitmap> mMemoryCache = null;

	public static void createMemoryCacheIfNeeded(Context context) {
		if (mMemoryCache != null) {
			if (DEBUG)
				Log.v(TAG,
						"createMemoryCacheIfNeeded(): memory cache already exist");
			return;
		}
		// Get memory class of this device, exceeding this amount will throw
		// an OutOfMemory exception.
		final int memClass = ((ActivityManager) context
				.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();
		// Use 1/3th of the available memory for this memory cache.
		final int cacheSize = 1024 * 1024 * memClass / 3;
		mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {

			@Override
			protected Bitmap create(String key) {
				if (DEBUG)
					Log.v(TAG, "create: " + key);
				return super.create(key);
			}

			@Override
			protected void entryRemoved(boolean evicted, String key,
					Bitmap oldValue, Bitmap newValue) {
				if (DEBUG)
					Log.v(TAG, "entryRemoved: " + key);
				super.entryRemoved(evicted, key, oldValue, newValue);
			}

			@Override
			protected int sizeOf(String key, Bitmap value) {
				if (DEBUG)
					Log.v(TAG, "sizeOf: " + key);
				if (value == null) {
					return 0;
				} else {
					Config config = value.getConfig();
					if (DEBUG)
						Log.v(TAG, "sizeOf: bitmap config " + config);
					int pixelBytes = 0;
					if (config.compareTo(Config.ARGB_8888) == 0) {
						pixelBytes = 4;
					} else if (config.compareTo(Config.ARGB_4444) == 0) {
						pixelBytes = 2;
					} else if (config.compareTo(Config.RGB_565) == 0) {
						pixelBytes = 2;
					} else if (config.compareTo(Config.ALPHA_8) == 0) {
						pixelBytes = 1;
					} else {
						if (DEBUG)
							Log.e(TAG, "sizeOf: unknown bitmap config");
						pixelBytes = 4;
					}
					return value.getWidth() * value.getHeight() * pixelBytes;
				}
			}
		};
	}

	public static Bitmap getBitmapFromMemoryCache(String key) {
		return mMemoryCache.get(key);
	}

	public static void addBitmapToMemoryCache(String key, Bitmap bitmap) {
		if (getBitmapFromMemoryCache(key) == null) {
			mMemoryCache.put(key, bitmap);
		}
	}

	/**
	 * An image file can be loaded into different size, thus those bitmaps
	 * should be considered different. Given the image file's path and the
	 * bitmap's size, returns an unique key
	 * 
	 * @param path
	 *            can be remote or local path. A remote path will be converted
	 *            to local path
	 * @param width
	 * @param height
	 */
	public static String getBitmapKey(String path, int width, int height) {
		if (path == null) {
			return null;
		}
		String localPath = FileUtil.getLocalCachePath(path);
		if (width <= 0 || height <= 0) {
			return localPath;
		}
		return localPath + "_" + width + "_" + height;
	}
}
